using Engine;
using Game;
using GameEntitySystem;
using TemplatesDatabase;

namespace SCIENEW {
    public class ComponentLiquidPump : ComponentInventoryTankBase, IUpdateable {
        public UpdateOrder UpdateOrder => UpdateOrder.Default;

        public ComponentBlockEntity m_componentBlockEntity;
        public SubsystemEnginePower m_subsystemEnginePower;

        public override int GetSlotCapacity(int slotIndex, int value) {
            if (Terrain.ExtractContents(value) == BaseDamageableItemBlock.Index
                && DamageableItemManager.GetItem(value) is TubularisDItem) {//只允许放管子
                return base.GetSlotCapacity(slotIndex, value);
            }
            return 0;
        }

        public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap) {
            base.Load(valuesDictionary, idToEntityMap);
            m_componentBlockEntity = Entity.FindComponent<ComponentBlockEntity>(true);
            m_subsystemEnginePower = Project.FindSubsystem<SubsystemEnginePower>(true);
            m_tanks[0].Capacity = m_tanks[1].Capacity = m_tanks[2].Capacity = m_tanks[3].Capacity = 3 * 4f;
        }

        public void Update(float dt) {
        }

        public void Pump(SubsystemTerrain subsystemTerrain) {
            Point3 point = m_componentBlockEntity.Coordinates;

            //检查电力
            if (!m_subsystemEnginePower.IsPowered(point, out _)) return;

            //检查管子
            bool empty = true;
            foreach (var slot in m_slots) {
                if (slot?.Count > 0) {
                    empty = false;
                    break;
                }
            }
            if (empty) return;

            int face = DevicesUtils.GetInnerData(subsystemTerrain.Terrain.GetCellValueFast(point.X, point.Y, point.Z));
            Vector3 faceVector = -CellFace.FaceToVector3(face);
            int x = point.X;
            int y = point.Y;
            int z = point.Z;

            int[] xOffsets = [0, 0, 1, 1, 1, 0, -1, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2];
            int[] zOffsets = [0, -1, -1, 0, 1, 1, 1, 0, -1, -2, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2];

            for (int depth = 1; depth < 8; depth++) {
                for (int phase = 0; phase < 25; phase++) {
                    x = point.X - (int)faceVector.X * depth;
                    y = point.Y - (int)faceVector.Y * depth;
                    z = point.Z - (int)faceVector.Z * depth;
                    if (faceVector.X != 0f)
                    {
                        y = point.Y + xOffsets[phase];
                        z = point.Z + zOffsets[phase];
                    }
                    if (faceVector.Y != 0f)
                    {
                        x = point.X + xOffsets[phase];
                        z = point.Z + zOffsets[phase];
                    }
                    if (faceVector.Z != 0f)
                    {
                        x = point.X + xOffsets[phase];
                        y = point.Y + zOffsets[phase];
                    }
                    int cellValue = Terrain.ReplaceLight(subsystemTerrain.Terrain.GetCellValue(x, y, z), 0);//指定坐标方块完整值
                    int content = Terrain.ExtractContents(cellValue);//指定坐标方块特殊值

                    bool canBePump = (FluidsManager.FluidToBlock.ContainsValue(cellValue) || FluidsManager.FluidToBlock.ContainsValue(content)) && BlocksManager.Blocks[content] is FluidBlock fluidBlock;//判断指定坐标格液体是否可被泵起
                    if (canBePump) {
                        int fluidLevel = FluidBlock.GetLevel(Terrain.ExtractData(cellValue));
                        if (fluidLevel != 0) continue;//不是满的流体，继续

                        int fluidID = FluidsManager.FluidToBlock.ContainsValue(cellValue) ? FluidsManager.FluidToBlock[second: cellValue] : FluidsManager.FluidToBlock[second: content];
                        float fillingFluidVolume = 4;
                        if (FindAcquireTankForFluid(this, fluidID) != -1) {//可以存下流体
                            AcquireFluid(this, fluidID, fillingFluidVolume);
                            //舀起液体
                            subsystemTerrain.ChangeCell(x, y, z, 0);

                            //损耗耐久
                            foreach (var slot in m_slots) {
                                if (slot == null) continue;
                                if (slot.Value == 0 || slot.Count == 0) continue;
                                int damage = DamageableItemManager.GetDamage(slot.Value);
                                slot.Value = DamageableItemManager.SetDamage(slot.Value, damage + 1);
                                if (BlocksManager.Blocks[BaseDamageableItemBlock.Index].GetBlockHealth(slot.Value) < 0) slot.Count--;//损坏
                                break;
                            }
                            return;
                        }
                    }
                }
            }
        }
    }
}